import cv2 as cv
import numpy as np


class DrawingApp:
    def __init__(self, width=512, height=512):
        self.canvas = np.zeros((height, width, 3), dtype=np.uint8)
        self.temp_canvas = self.canvas.copy()
        self.drawing = False
        self.mode = False  # False: circle, True: rectangle
        self.start_point = (-1, -1)
        self.color = (0, 255, 0)
        self.window_name = 'Drawing Board'

    def run(self):
        cv.namedWindow(self.window_name)
        cv.setMouseCallback(self.window_name, self.mouse_events)

        while True:
            cv.imshow(self.window_name, self.canvas)
            key = cv.waitKey(1) & 0xFF

            if key == ord('m'):
                self.mode = not self.mode
                print(f"Switched to {'rectangle' if self.mode else 'circle'} mode")

            elif key == ord('c'):
                self.color = tuple(np.random.randint(0, 256, 3).tolist())
                print(f"Color changed to: {self.color}")

            elif key == ord('r'):
                self.canvas[:] = 0
                self.temp_canvas = self.canvas.copy()
                print("Canvas reset")

            elif key == 27:
                break

        cv.destroyAllWindows()

    def mouse_events(self, event, x, y, flags, param):
        if event == cv.EVENT_LBUTTONDOWN:
            self.drawing = True
            self.start_point = (x, y)
            self.temp_canvas = self.canvas.copy()

        elif event == cv.EVENT_MOUSEMOVE and self.drawing:
            preview = self.temp_canvas.copy()
            if self.mode:
                cv.rectangle(preview, self.start_point, (x, y), self.color, 2)
            else:
                radius = int(np.hypot(x - self.start_point[0], y - self.start_point[1]))
                cv.circle(preview, self.start_point, radius, self.color, 2)
            cv.imshow(self.window_name, preview)

        elif event == cv.EVENT_LBUTTONUP:
            self.drawing = False
            if self.mode:
                cv.rectangle(self.canvas, self.start_point, (x, y), self.color, 2)
            else:
                radius = int(np.hypot(x - self.start_point[0], y - self.start_point[1]))
                cv.circle(self.canvas, self.start_point, radius, self.color, 2)
            cv.imshow(self.window_name, self.canvas)


if __name__ == '__main__':
    app = DrawingApp()
    app.run()
